package com.woniuxy.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.entity.DTO.UserInfoDTO;
import com.woniuxy.enums.user.SocialRelationshipStatus;
import com.woniuxy.enums.user.SocialRelationshipType;
import com.woniuxy.core.service.AllUserService;
import com.woniuxy.core.service.UserStatsService;
import com.woniuxy.entity.AllUser;
import com.woniuxy.entity.SocialRelationship;
import com.woniuxy.core.service.SocialRelationshipService;
import com.woniuxy.core.mapper.SocialRelationshipMapper;
import com.woniuxy.entity.UserStats;
import com.woniuxy.enums.redis.user.UserRedisKeyEnum;
import com.woniuxy.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 35123
 * @description 针对表【social_relationship(用户社交关系表)】的数据库操作Service实现
 * @createDate 2025-07-12 11:31:28
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SocialRelationshipServiceImpl extends ServiceImpl<SocialRelationshipMapper, SocialRelationship>
        implements SocialRelationshipService {

    private final UserStatsService userStatsService;

    private final AllUserService allUserService;

    // 注入Redis工具类
    private final RedisUtil redisUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void followUser(Long userId, Long targetId) {

        // 校验不能关注自己
        if (Objects.equals(userId, targetId)) {
            throw new IllegalArgumentException("不能关注自己");
        }

        // 查询当前用户对目标用户的现有关系(正常或已解除)
        QueryWrapper<SocialRelationship> currentQuery = new QueryWrapper<>();
        currentQuery.eq("user_id", userId)
                .eq("target_id", targetId)
                .in("status", SocialRelationshipStatus.NORMAL.getStatus(), SocialRelationshipStatus.UNFOLLOW.getStatus());
        SocialRelationship currentRelationship = getOne(currentQuery, false);

        // 查询目标用户对当前用户的反向关系(仅正常状态)
        QueryWrapper<SocialRelationship> reverseQuery = new QueryWrapper<>();
        reverseQuery.eq("user_id", targetId)
                .eq("target_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()); // 反向关系需为正常状态才可能形成互关
        SocialRelationship reverseRelation = getOne(reverseQuery, false);

        if (currentRelationship != null) {
            log.debug("线程[{}]进入更新分支，当前关系存在", Thread.currentThread().getId());
            // 存在现有关系：
            // 正常状态则报错
            if (Objects.equals(currentRelationship.getStatus(), SocialRelationshipStatus.NORMAL.getStatus())) {
                throw new RuntimeException("已关注该用户");
            }
            // 已解除状态则恢复正常
            currentRelationship.setStatus(SocialRelationshipStatus.NORMAL.getStatus());

            // 根据反向关系是否存在更新当前关系的类型
            if (reverseRelation != null) {
                // 反向关系存在，设为互关
                currentRelationship.setRelationType(SocialRelationshipType.MUTUAL.getType());
            } else {
                // 反向关系不存在，设为单向关注
                currentRelationship.setRelationType(SocialRelationshipType.FOLLOW.getType());
            }
            currentRelationship.setUpdateTime(new Date());

            if (!updateById(currentRelationship)) {
                log.error("关注关系恢复正常失败：{}", currentRelationship);
                throw new RuntimeException("操作太频繁，请稍后再试");
            }

            // 如果当前关系升级为互关，同步升级反向关系的类型
            if (reverseRelation != null && Objects.equals(currentRelationship.getRelationType(), SocialRelationshipType.MUTUAL.getType())) {
                boolean reverseUpdateSuccess = update()
                        .set("relation_type", SocialRelationshipType.MUTUAL.getType())
                        .set("update_time", new Date())
                        .eq("id", reverseRelation.getId())
                        .eq("relation_type", SocialRelationshipType.FOLLOW.getType()) // 仅单向关注时升级
                        .update();
                if (!reverseUpdateSuccess) {
                    log.warn("反向关系升级互关失败（可能已被其他请求修改）：{}", reverseRelation);
                    throw new RuntimeException("操作太频繁，请稍后再试");
                }
                log.debug("反向关系升级为互关：{}", reverseRelation);
            }
        } else {
            log.debug("线程[{}]进入插入分支，当前关系不存在", Thread.currentThread().getId());
            // 不存在现有关系：
            // 新增关注记录(初始类型根据反向关系判断)
            SocialRelationship newRelationship = new SocialRelationship();
            newRelationship.setUserId(userId);
            newRelationship.setTargetId(targetId);
            newRelationship.setStatus(SocialRelationshipStatus.NORMAL.getStatus());
            // 反向关系存在则为互关，否则为单向关注
            Integer type = reverseRelation == null ? SocialRelationshipType.FOLLOW.getType() : SocialRelationshipType.MUTUAL.getType();
            newRelationship.setRelationType(type);
            newRelationship.setCreateTime(new Date());
            newRelationship.setVersion(0L);
            try {
                if (!(save(newRelationship))) {
                    throw new RuntimeException("新增关系记录失败");
                }
            } catch (DuplicateKeyException e) {
                // 唯一约束冲突（如并发插入相同关注记录）
                log.warn("用户[{}]重复关注用户[{}]", userId, targetId);
                throw new RuntimeException("已关注该用户");
            }
            log.debug("新增关注关系：{}", newRelationship);

//            // 反向正常关系存在且当前是新增关注时，升级反向关系为互关
//            if (reverseRelation != null) {
//                reverseRelation.setRelationType(SocialRelationshipType.MUTUAL.getType());
//                updateById(reverseRelation);
//                log.debug("反向关系升级为互关：{}", reverseRelation);
//            }
        }

        // 更新当前用户的关注集合（Set集合）
        String userFollowSetKey = UserRedisKeyEnum.USER_FOLLOW_SET.format(userId);
        redisUtil.sAdd(userFollowSetKey, targetId);

        // 更新当前用户的关注数 (+1)
        boolean followUpdateSuccess = userStatsService.update()
                .setSql("follow_count = follow_count + 1")// 保证原子性，避免并发问题
                .eq("user_id", userId)
                .update();
        if (!followUpdateSuccess) {
            log.error("用户[{}]统计记录不存在，关注数更新失败", userId);
            throw new RuntimeException("系统出现错误！关注失败");
        }

        // 更新目标用户的粉丝数（+1）
        boolean fanUpdateSuccess = userStatsService.update()
                .setSql("fan_count = fan_count + 1")
                .eq("user_id", targetId)
                .update();
        if (!fanUpdateSuccess) {
            log.error("用户[{}]统计记录不存在，粉丝数更新失败", targetId);
            throw new RuntimeException("系统出现错误！关注失败");
        }

        // 反向正常关系存在且当前是新增关注时，升级反向正常关系为互关
        if (reverseRelation != null && currentRelationship == null) {
            reverseRelation.setRelationType(SocialRelationshipType.MUTUAL.getType());

            if (!updateById(reverseRelation)) {
                log.error("反向关系升级互关失败：{}", reverseRelation);
                throw new RuntimeException("操作太频繁，请稍后再试");
            }
            log.debug("反向关系升级为互关：{}", reverseRelation);
        }

        // 注册事务提交后的回调
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                // 仅在事务成功提交后更新同步Redis缓存
                updateUserStatsCache(userId);
                updateUserStatsCache(targetId);
                // 清除当前用户所有分页的关注列表、粉丝列表、互关列表缓存(通配符匹配)
                String followCachePattern = UserRedisKeyEnum.FOLLOW_LIST.format(userId, "*", "*");
                String fansCachePattern = UserRedisKeyEnum.FANS_LIST.format(targetId, "*", "*");
                String mutualCachePattern = UserRedisKeyEnum.MUTUAL_FOLLOW_LIST.format(userId, "*", "*");

                int retryCount = 3;
                while (retryCount-- > 0) {
                    try {
                        redisUtil.delByPattern(followCachePattern);
                        redisUtil.delByPattern(fansCachePattern);
                        redisUtil.delByPattern(mutualCachePattern);
                        log.debug("清除用户[{}]关注列表、粉丝列表、互关列表缓存成功", userId);
                        break;
                    } catch (Exception e) {
                        log.error("缓存清除失败，剩余重试次数：{}，错误：{}", retryCount, e.getMessage());
                        if (retryCount == 0) {
                            log.error("缓存清除最终失败，用户[{}]，可能影响后续查询一致性", userId);
                            throw new RuntimeException("系统繁忙，请稍后再试");
                        }
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ignored) {
                        }
                    }
                }
            }
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unfollowUser(Long userId, Long targetId) {

        // 校验不能关注自己
        if (Objects.equals(userId, targetId)) {
            throw new IllegalArgumentException("非法操作");
        }

        // 查询当前用户对目标用户的正常关系(必须存在且状态为正常)
        QueryWrapper<SocialRelationship> currentQuery = new QueryWrapper<>();
        currentQuery.eq("user_id", userId)
                .eq("target_id", targetId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()); // 仅允许取消正常状态的关注
        SocialRelationship currentRelationship = getOne(currentQuery, false);
        if (currentRelationship == null) {
            throw new RuntimeException("未关注该用户，无法取消");
        }

        // 更新当前用户关系状态为已解除，并恢复relation_type为单向关注
        currentRelationship.setStatus(SocialRelationshipStatus.UNFOLLOW.getStatus());
        currentRelationship.setRelationType(SocialRelationshipType.FOLLOW.getType());
        currentRelationship.setUpdateTime(new Date());

        if (!updateById(currentRelationship)) {
            log.error("关注关系更新为已解除失败：{}", currentRelationship);
            throw new RuntimeException("操作太频繁，请稍后再试");
        }

        // 查询反向关系（目标用户对当前用户的关系）
        QueryWrapper<SocialRelationship> reverseQuery = new QueryWrapper<>();
        reverseQuery.eq("user_id", targetId)
                .eq("target_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus());
        SocialRelationship reverseRelation = getOne(reverseQuery, false);

        if (reverseRelation != null && Objects.equals(
                reverseRelation.getRelationType(), SocialRelationshipType.MUTUAL.getType())) {
            // 若反向关系存在且类型为互关，降级为单向关注
            boolean reverseUpdateSuccess = update()
                    .set("relation_type", SocialRelationshipType.FOLLOW.getType())
                    .set("update_time", new Date())
                    .eq("id", reverseRelation.getId())
                    .eq("relation_type", SocialRelationshipType.MUTUAL.getType()) // 仅互关时降级
                    .update();
            if (!reverseUpdateSuccess) {
                log.warn("反向关系降级为单向关注失败（可能已被其他请求修改）：{}", reverseRelation);
                throw new RuntimeException("操作太频繁，请稍后再试");
            }
            log.debug("反向互关关系降级为单向关注：{}", reverseRelation);
        }

        // 清除用户关注集合中的目标用户ID(Set集合)
        String userFollowSetKey = UserRedisKeyEnum.USER_FOLLOW_SET.format(userId);
        redisUtil.sRemove(userFollowSetKey, targetId);

        // 更新当前用户的关注数 (-1)
        boolean followUpdateSuccess = userStatsService.update()
                .setSql("follow_count = follow_count - 1")
                .eq("user_id", userId)
                .update();
        if (!followUpdateSuccess) {
            log.error("用户[{}]统计记录不存在，关注数更新失败", userId);
            throw new RuntimeException("系统出现错误！取消关注失败");
        }

        // 更新目标用户的粉丝数（-1）
        boolean fanUpdateSuccess = userStatsService.update()
                .setSql("fan_count = fan_count - 1")
                .eq("user_id", targetId)
                .update();
        if (!fanUpdateSuccess) {
            log.error("用户[{}]统计记录不存在，粉丝数更新失败", targetId);
            throw new RuntimeException("系统错误！取消关注失败");
        }

        // 事务提交后同步更新Redis缓存
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                updateUserStatsCache(userId);
                updateUserStatsCache(targetId);
                // 清除当前用户所有分页的关注列表、粉丝列表、互关列表缓存
                String followCachePattern = UserRedisKeyEnum.FOLLOW_LIST.format(userId, "*", "*");
                String fansCachePattern = UserRedisKeyEnum.FANS_LIST.format(targetId, "*", "*");
                String mutualCachePattern = UserRedisKeyEnum.MUTUAL_FOLLOW_LIST.format(userId, "*", "*");

                int retryCount = 3;
                while (retryCount-- > 0) {
                    try {
                        redisUtil.delByPattern(followCachePattern);
                        redisUtil.delByPattern(fansCachePattern);
                        redisUtil.delByPattern(mutualCachePattern);
                        log.debug("清除用户[{}]关注列表、粉丝列表、互关列表缓存成功", userId);
                        break;
                    } catch (Exception e) {
                        log.error("缓存清除失败，剩余重试次数：{}，错误：{}", retryCount, e.getMessage());
                        if (retryCount == 0) {
                            log.error("缓存清除最终失败，用户[{}]，可能影响后续查询一致性", userId);
                            throw new RuntimeException("系统繁忙，请稍后再试");
                        }
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ignored) {
                        }
                    }
                }
            }
        });

    }


    @Override
    public Page<UserInfoDTO> getFollowList(Integer userId, Page<UserInfoDTO> page) {

        String redisKey = UserRedisKeyEnum.FOLLOW_LIST.format(userId, page.getCurrent(), page.getSize());

        // 优先查询Redis缓存
        Page<UserInfoDTO> cachePage = (Page<UserInfoDTO>) redisUtil.get(redisKey);
        if (cachePage != null) {
            log.debug("从Redis获取关注列表缓存，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());
            return cachePage;
        }

        // 创建 SocialRelationship 类型的分页对象
        Page<SocialRelationship> relationshipPage = new Page<>(page.getCurrent(), page.getSize());

        // 查询当前用户的所有正常关注记录（分页）
        QueryWrapper<SocialRelationship> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()); // 仅查询正常状态的关注
        relationshipPage = page(relationshipPage, queryWrapper); // 使用 SocialRelationship 类型的分页对象查询

        // 提取所有目标用户ID
        List<Long> targetUserIds = relationshipPage.getRecords().stream()
                .map(SocialRelationship::getTargetId)
                .collect(Collectors.toList());

        if (targetUserIds.isEmpty()) {
            Page<UserInfoDTO> emptyPage = new Page<>(page.getCurrent(), page.getSize(), 0);// 无关注用户，返回空分页
            redisUtil.set(redisKey, emptyPage, 30 * 60); // 缓存空结果
            return emptyPage;
        }

        // 调用用户服务获取目标用户详细信息
        List<AllUser> followers = allUserService.listByIds(targetUserIds);

        // 批量查询目标用户对当前用户的关注关系
        QueryWrapper<SocialRelationship> reverseQuery = new QueryWrapper<>();
        reverseQuery.in("user_id", targetUserIds)
                .eq("target_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus());
        List<SocialRelationship> followRelations = list(reverseQuery);

        // 构建目标用户ID -> 是否互关的映射表
        Map<Long, Boolean> isMutualMap = followRelations.stream()
                .collect(Collectors.toMap(
                        SocialRelationship::getUserId,
                        r -> true,
                        (oldValue, newValue) -> oldValue // 处理重复键（如果存在），保留旧值
                ));

        List<UserInfoDTO> dtoList = followers.stream()
                .map(targetUser -> {
                    UserInfoDTO dto = new UserInfoDTO();
                    BeanUtils.copyProperties(targetUser, dto);

                    // 判断当前用户是否关注目标用户（当前关注列表，必然为 true）
                    dto.setIsFollowed(true);

                    // 从映射表中获取是否互关
                    dto.setIsMutual(isMutualMap.getOrDefault(targetUser.getUserId(), false));

                    return dto;
                }).collect(Collectors.toList());

        // 封装最终分页结果（同步总记录数、当前页、每页大小）
        Page<UserInfoDTO> resultPage = new Page<>();
        resultPage.setCurrent(relationshipPage.getCurrent());
        resultPage.setSize(relationshipPage.getSize());
        resultPage.setTotal(relationshipPage.getTotal());
        resultPage.setRecords(dtoList); // 填充用户信息

        // 将结果存入Redis（缓存30分钟）
        redisUtil.set(redisKey, resultPage, 30 * 60);
        log.debug("关注列表已缓存到Redis，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());

        return resultPage;
    }

    @Override
    public Page<UserInfoDTO> getFansList(Integer userId, Page<UserInfoDTO> page) {

        String redisKey = UserRedisKeyEnum.FANS_LIST.format(userId, page.getCurrent(), page.getSize());

        // 优先查询Redis缓存
        Page<UserInfoDTO> cachePage = (Page<UserInfoDTO>) redisUtil.get(redisKey);
        if (cachePage != null) {
            log.debug("从Redis获取粉丝列表缓存，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());
            return cachePage;
        }

        // 查询当前用户作为被关注目标的正常关系记录（分页）
        Page<SocialRelationship> relationshipPage = new Page<>(page.getCurrent(), page.getSize());
        QueryWrapper<SocialRelationship> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("target_id", userId) // 粉丝的targetId是当前用户
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()); // 仅正常状态的关注

        relationshipPage = page(relationshipPage, queryWrapper); // 执行分页查询

        // 提取所有粉丝的用户ID（即关系中的userId）
        List<Long> fanUserIds = relationshipPage.getRecords().stream()
                .map(SocialRelationship::getUserId)
                .collect(Collectors.toList());

        if (fanUserIds.isEmpty()) {
            Page<UserInfoDTO> emptyPage = new Page<>(page.getCurrent(), page.getSize(), 0);
            redisUtil.set(redisKey, emptyPage, 30 * 60); // 缓存空结果
            return emptyPage;
        }

        // 调用用户服务获取粉丝详细信息
        List<AllUser> fans = allUserService.listByIds(fanUserIds);

        // 批量查询当前用户对这些粉丝的关注状态（避免循环中多次查询）
        QueryWrapper<SocialRelationship> followQuery = new QueryWrapper<>();
        followQuery.eq("user_id", userId) // 当前用户作为主动关注方
                .in("target_id", fanUserIds) // 目标ID是粉丝列表中的用户
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus());
        List<SocialRelationship> followRelations = list(followQuery);

        // 构建targetId -> 是否关注的映射
        Map<Long, Boolean> isFollowedMap = followRelations.stream()
                .collect(Collectors.toMap(
                        SocialRelationship::getTargetId, // 目标ID（粉丝ID）
                        r -> true, // 存在记录即表示已关注
                        (oldVal, newVal) -> oldVal // 去重（理论上不会重复）
                ));


        List<UserInfoDTO> dtoList = fans.stream()
                .map(fan -> {
                    UserInfoDTO dto = new UserInfoDTO();
                    BeanUtils.copyProperties(fan, dto);

                    // 判断当前用户是否关注该粉丝（从批量查询的映射中获取）
                    boolean isFollowed = isFollowedMap.getOrDefault(fan.getUserId(), false);
                    dto.setIsFollowed(isFollowed);

                    // 互关状态：粉丝已关注当前用户（否则不会出现在列表），所以isMutual等于isFollowed
                    dto.setIsMutual(isFollowed);

                    return dto;
                }).collect(Collectors.toList());

        // 封装分页结果（同步总记录数、当前页、每页大小）
        Page<UserInfoDTO> resultPage = new Page<>();
        resultPage.setCurrent(relationshipPage.getCurrent());
        resultPage.setSize(relationshipPage.getSize());
        resultPage.setTotal(relationshipPage.getTotal());
        resultPage.setRecords(dtoList);

        // 缓存结果到Redis（30分钟）
        redisUtil.set(redisKey, resultPage, 30 * 60);
        log.debug("粉丝列表已缓存到Redis，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());

        return resultPage;
    }

    @Override
    public Page<UserInfoDTO> getMutualFollowList(Integer userId, Page<UserInfoDTO> page) {

        String redisKey = UserRedisKeyEnum.MUTUAL_FOLLOW_LIST.format(userId, page.getCurrent(), page.getSize());

        // 优先查询Redis缓存
        Page<UserInfoDTO> cachePage = (Page<UserInfoDTO>) redisUtil.get(redisKey);
        if (cachePage != null) {
            log.debug("从Redis获取互关列表缓存，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());
            return cachePage;
        }

        // 查询当前用户的互关关系记录（分页）
        Page<SocialRelationship> relationshipPage = new Page<>(page.getCurrent(), page.getSize());
        QueryWrapper<SocialRelationship> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()) // 仅正常状态
                .eq("relation_type", SocialRelationshipType.MUTUAL.getType()); // 仅互关类型

        relationshipPage = page(relationshipPage, queryWrapper); // 执行分页查询

        // 提取所有互关用户的ID（即关系中的targetId）
        List<Long> mutualUserIds = relationshipPage.getRecords().stream()
                .map(SocialRelationship::getTargetId)
                .collect(Collectors.toList());

        if (mutualUserIds.isEmpty()) {
            Page<UserInfoDTO> emptyPage = new Page<>(page.getCurrent(), page.getSize(), 0);
            redisUtil.set(redisKey, emptyPage, 30 * 60); // 缓存空结果
            return emptyPage;
        }

        // 调用用户服务获取互关用户详细信息
        List<AllUser> mutualUsers = allUserService.listByIds(mutualUserIds);

        // 转换为UserInfoDTO列表
        List<UserInfoDTO> dtoList = mutualUsers.stream()
                .map(user -> {
                    UserInfoDTO dto = new UserInfoDTO();
                    BeanUtils.copyProperties(user, dto);
                    dto.setIsFollowed(true);
                    dto.setIsMutual(true);
                    return dto;
                })
                .collect(Collectors.toList());

        // 封装分页结果（同步总记录数、当前页、每页大小）
        Page<UserInfoDTO> resultPage = new Page<>();
        resultPage.setCurrent(relationshipPage.getCurrent());
        resultPage.setSize(relationshipPage.getSize());
        resultPage.setTotal(relationshipPage.getTotal());
        resultPage.setRecords(dtoList);

        // 缓存结果到Redis（30分钟）
        redisUtil.set(redisKey, resultPage, 30 * 60);
        log.debug("互关列表已缓存到Redis，userId={}, page={}, size={}", userId, page.getCurrent(), page.getSize());

        return resultPage;
    }


    @Override
    public Long countMutualFollow(Integer userId) {
        // 查询当前用户的正常互关关系数量
        QueryWrapper<SocialRelationship> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus()) // 仅正常状态
                .eq("relation_type", SocialRelationshipType.MUTUAL.getType()); // 仅互关类型
        return count(queryWrapper);
    }

    /**
     * 同步用户统计信息到Redis
     *
     * @param userId 用户ID
     */
    private void updateUserStatsCache(Long userId) {
        // 查询最新的用户统计信息
        UserStats userStats = userStatsService.getUserStatsByUserId(userId);
        if (userStats != null) {
            // 生成Redis键（使用UserRedisKeyEnum）
            String redisKey = UserRedisKeyEnum.USER_STATS.format(userId);
            // 缓存30分钟（根据业务需求调整过期时间）
            redisUtil.set(redisKey, userStats, 30 * 60);
            log.debug("用户[{}]统计信息已缓存到Redis，键：{}", userId, redisKey);
        } else {
            log.warn("用户[{}]统计记录不存在，未缓存到Redis", userId);
        }
    }

    @Override
    public Boolean isUserFollowed(Long userId, Long targetId) {
        if (userId == null || targetId == null || userId.equals(targetId)) {
            return false;
        }

        QueryWrapper<SocialRelationship> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("target_id", targetId)
                .eq("status", SocialRelationshipStatus.NORMAL.getStatus())
                .in("relation_type",
                        SocialRelationshipType.FOLLOW.getType(),  // 单向关注
                        SocialRelationshipType.MUTUAL.getType()   // 互关
                );

        return this.count(queryWrapper) > 0;
    }

    @Override
    public List<UserInfoDTO> recommendFriends(Long userId) {

        String userRecommendation = UserRedisKeyEnum.USER_RECOMMENDATION_LIST.format(userId);
        // 优先查询Redis缓存
        List<UserInfoDTO> cacheList = (List<UserInfoDTO>) redisUtil.get(userRecommendation);
        if (cacheList != null) {
            log.debug("从Redis获取用户推荐好友列表缓存，userId={}, size={}", userId, cacheList.size());
            return cacheList;
        }

        // 生成 3-8 个随机目标数量
        int targetCount = new Random().nextInt(6) + 3;

        // 获取当前用户的关注集合
        String userFollowSetKey = UserRedisKeyEnum.USER_FOLLOW_SET.format(userId);
        Set<Object> userFollowSet = redisUtil.members(userFollowSetKey);

        // 无关注好友时返回备选推荐方案
        if (userFollowSet.isEmpty()) {
            return getBackupRecommendations(userId, targetCount);
        }

        // 收集所有好友的关注集合并统计共同好友数
        Map<Long, Integer> candidateCountMap = new HashMap<>();
        for (Object friendObj : userFollowSet) {
            Long friendId = ((Number) friendObj).longValue();
            String friendFollowSetKey = UserRedisKeyEnum.USER_FOLLOW_SET.format(friendId);
            // 使用Redis的随机获取方法（随机取50个关注用户，避免全量扫描）
            List<Object> friendFollowed = redisUtil.randomMembers(friendFollowSetKey, 50);

            // 统计每个潜在用户被当前用户好友关注的次数（共同好友数）
            for (Object candidateIdObj : friendFollowed) {
                Long candidateId = ((Number) candidateIdObj).longValue();
                // 排除当前用户自己
                if (candidateId.equals(userId))
                    continue;
                // 统计共同好友数
                candidateCountMap.put(candidateId, candidateCountMap.getOrDefault(candidateId, 0) + 1);
            }
        }

        // 过滤已关注/互关的用户
        Set<Long> followedUserIds = getFollowedUserIds(userId);
        List<Long> filteredCandidates = candidateCountMap.keySet()
                .stream()
                .filter(candidateId -> !followedUserIds.contains(candidateId)) // 过滤当前用户已关注的用户
                .sorted((c1, c2) -> candidateCountMap.get(c2).compareTo(candidateCountMap.get(c1))) // 按共同好友数降序排序
                .limit(targetCount)
                .collect(Collectors.toList());
        List<UserInfoDTO> finalRecommendations = convertToUserInfoDTO(filteredCandidates, candidateCountMap);

        // 推荐好友候选不足时补充备选推荐
        if (finalRecommendations.size() < targetCount) {
            log.debug("推荐好友候选不足，补充备选推荐，userId={}, currentSize={}, targetSize={}", userId, finalRecommendations.size(), targetCount);
            int needCount = targetCount - finalRecommendations.size();
            List<UserInfoDTO> backupCandidates = getBackupRecommendations(userId, needCount * 2); // 多取2倍防重复

            for (UserInfoDTO dto : backupCandidates) {
                if (finalRecommendations.size() >= targetCount)
                    break;
                // 排除已推荐的好友候选
                if (!filteredCandidates.contains(dto.getUserId())) {
                    finalRecommendations.add(dto);
                }
            }
        }

        // 备选仍不足时随机补充系统用户
        if (finalRecommendations.size() < targetCount) {
            log.debug("推荐好友备选不足，补充随机系统用户，userId={}, currentSize={}, targetSize={}", userId, finalRecommendations.size(), targetCount);
            int needCount = targetCount - finalRecommendations.size();
            List<UserInfoDTO> randomUsers = getRandomSystemUsers(userId, needCount * 2);

            for (UserInfoDTO dto : randomUsers) {
                if (finalRecommendations.size() >= targetCount)
                    break;
                // 还是需要排除已推荐的好友候选
                if (!filteredCandidates.contains(dto.getUserId())) {
                    finalRecommendations.add(dto);
                }
            }
        }

        // 缓存推荐结果到Redis（12小时）
        redisUtil.set(userRecommendation, finalRecommendations, 12 * 60 * 60);
        log.debug("用户[{}]推荐好友列表已缓存到Redis，键：{}，列表大小：{}", userId, userRecommendation, finalRecommendations.size());

        return finalRecommendations;
    }

    /**
     * 获取当前用户已关注的用户ID集合（包括互关用户）
     *
     * @param userId 用户ID
     * @return 关注用户ID集合
     */
    private Set<Long> getFollowedUserIds(Long userId) {
        String userFollowSetKey = UserRedisKeyEnum.USER_FOLLOW_SET.format(userId);
        Set<Object> userFollowSet = redisUtil.members(userFollowSetKey);

        return userFollowSet.stream()
                .map(obj -> ((Number) obj).longValue())
                .collect(Collectors.toSet());
    }

    /**
     * 转换为UserInfoDTO列表
     *
     * @param userIds           用户ID列表
     * @param candidateCountMap 共同好友数映射
     * @return UserInfoDTO列表
     */
    private List<UserInfoDTO> convertToUserInfoDTO(List<Long> userIds, Map<Long, Integer> candidateCountMap) {
        if (userIds.isEmpty()) {
            return Collections.emptyList();
        }

        // 批量查询用户信息
        List<AllUser> users = allUserService.listByIds(userIds);
        // 构建用户ID到用户对象的映射表（O(1)查找）
        Map<Long, AllUser> userIdToUserMap = users.stream()
                .collect(Collectors.toMap(AllUser::getUserId, user -> user));

        return userIds.stream()
                // 从映射表获取用户对象
                .map(userIdToUserMap::get)
                .filter(Objects::nonNull)
                // 转换为UserInfoDTO
                .map(user -> {
                    UserInfoDTO dto = new UserInfoDTO();
                    BeanUtils.copyProperties(user, dto);
                    // 设置共同好友数
                    dto.setCommonFriendCount(candidateCountMap.getOrDefault(user.getUserId(), 0));
                    return dto;
                })
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 获取备选推荐方案（按获赞数排序）
     *
     * @param userId 用户ID
     * @param need  推荐数量
     * @return UserInfoDTO列表
     */
    private List<UserInfoDTO> getBackupRecommendations(Long userId, int need) {
        // 获取按获赞数降序排序的用户统计列表
        List<UserStats> hotStats = userStatsService.list()
                .stream()
                .sorted((s1, s2) -> s2.getLikeCount().compareTo(s1.getLikeCount()))
                .collect(Collectors.toList());

        // 构建用户ID到获赞数的映射表
        Map<Long, Long> userLikeCountMap = hotStats.stream()
                .collect(Collectors.toMap(
                        UserStats::getUserId, // 键：用户ID
                        UserStats::getLikeCount, // 值：获赞数
                        (oldVal, newVal) -> oldVal // 合并函数（如果有重复键，保留旧值）
                ));

        // 提取所有需要查询的用户ID（避免逐个查询）
        List<Long> userIds = hotStats.stream()
                .map(UserStats::getUserId)
                .collect(Collectors.toList());

        // 批量查询用户信息
        List<AllUser> users = allUserService.listByIds(userIds);
        Map<Long, AllUser> userIdToUserMap = users.stream()
                .collect(Collectors.toMap(AllUser::getUserId, user -> user));

        // 获取当前用户已关注的用户ID集合（包括互关用户）
        Set<Long> followedUserIds = getFollowedUserIds(userId);

        // 过滤逻辑：排除自己、排除已关注用户，并取前 need 个
        return hotStats.stream()
                .map(stat -> userIdToUserMap.get(stat.getUserId()))
                .filter(Objects::nonNull)
                .filter(user -> {
                    // 排除当前用户
                    boolean isNotSelf = !user.getUserId().equals(userId);
                    // 排除已关注用户
                    boolean isNotFollowed = !followedUserIds.contains(user.getUserId());
                    // 获赞数大于1
                    boolean isLiked = userLikeCountMap.get(user.getUserId()) > 1;

                    return isNotSelf && isNotFollowed && isLiked;
                })
                .map(user -> {
                    UserInfoDTO dto = new UserInfoDTO();
                    BeanUtils.copyProperties(user, dto);
                    // 从获赞数映射表中获取值并设置获赞数
                    dto.setLikeCount(userLikeCountMap.get(user.getUserId()));
                    return dto;
                })
                .limit(need)
                .collect(Collectors.toList());
    }

    /**
     * 获取随机系统用户
     *
     * @param userId 用户ID
     * @param need  推荐数量
     * @return UserInfoDTO列表
     */
    private List<UserInfoDTO> getRandomSystemUsers(Long userId, int need) {
        // 随机查询系统用户ID
        List<Long> randomUserIds = allUserService.listRandomUserIds(need);

        // 批量查询用户信息
        List<AllUser> users = allUserService.listByIds(randomUserIds);
        // 转换为映射表
        Map<Long, AllUser> userIdToUserMap = users.stream()
                .collect(Collectors.toMap(AllUser::getUserId, user -> user));

        // 获取当前用户已关注的用户ID集合（包括互关用户）
        Set<Long> followedUserIds = getFollowedUserIds(userId);
        List<UserInfoDTO> randomUsers = new ArrayList<>();

        // 转换为UserInfoDTO
        for (Long uid : randomUserIds) {
            if (randomUsers.size() >= need) break;

            // 排除当前用户和已关注用户
            if (uid.equals(userId) || followedUserIds.contains(uid)) continue;

            // 从映射表中获取用户对象
            AllUser user = userIdToUserMap.get(uid);
            if (user != null) {
                UserInfoDTO dto = new UserInfoDTO();
                BeanUtils.copyProperties(user, dto);
                randomUsers.add(dto);
            }
        }

        return randomUsers;
    }

}




